package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmdp.dto.Result;
import com.hmdp.dto.ScrollResult;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.Blog;
import com.hmdp.entity.Follow;
import com.hmdp.entity.User;
import com.hmdp.mapper.BlogMapper;
import com.hmdp.service.IBlogService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.service.IFollowService;
import com.hmdp.service.IUserService;
import com.hmdp.utils.SystemConstants;
import com.hmdp.utils.UserHolder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class BlogServiceImpl extends ServiceImpl<BlogMapper, Blog> implements IBlogService {
    @Resource
    private IUserService userService;
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    private IFollowService followService;

    @Override
    public Result queryHotBlog(Integer current) {
        //首页展示触发
        //进入页面后,查询热度最高的博客
        Page<Blog> page = query()
                .orderByDesc("liked")
                // 按照点赞数降序排列
                .page(new Page<>(current, SystemConstants.MAX_PAGE_SIZE));
        // 分页查询，current是当前页数，MAX_PAGE_SIZE是每页大小
        List<Blog> records = page.getRecords();
        //此时的records 部分信息icon=null, name=null, isLike=null,
        records.forEach(blog->{
            this.queryBlogUser(blog);
            // 为每篇博客查询作者信息
            this.isBlogLiked(blog);
            // 检查当前用户是否已经点赞该博客
        });
        return Result.ok(records);
        // 返回查询结果
    }

    @Override
    public Result queryBlogById(Long id) {
//        从首页点击进入博客触发
        //根据博客 ID 查询博客详情
        Blog blog = getById(id);
        if (blog == null) {
            return Result.fail("笔记不存在!");
        }
        queryBlogUser(blog);
        isBlogLiked(blog);
        System.out.println("queryBlogById:blog" + blog);
        return Result.ok(blog); // 添加返回值，避免返回null
    }

    private void isBlogLiked(Blog blog) {
        //判断当前用户是否已点赞某个博客。
        UserDTO user=UserHolder.getUser();
        //获取当前用户
        System.out.println("isBlogLiked:user:"+user);
        if(user==null){
            return ;
        }
        Long userId =user.getId();
        //获取当前用户的id
      Double score=stringRedisTemplate.opsForZSet()
              .score("blog:liked:"+blog.getId(),userId.toString());
      //按照分数排名,第一个字段为博客的id,第二个字段为用户的id
        blog.setIsLike(score!=null);
        //判断 score 是否不为 null。如果 score 有值（不为 null），表达式的结果为 true
        System.out.println("score:"+score);
    }

    @Override
    public Result likeBlog(Long id) {
        //用户点赞或取消点赞某个博客
        //博客的id
        Long userId = UserHolder.getUser().getId();
        //获取当前登录用户的id
        Double score=stringRedisTemplate.opsForZSet().score("blog:liked:"+id,userId.toString());
        //传入id(key),还有点赞用户的id,设置对应分数的
        //zset有序集合,set无序集合
        //没有点赞则返回null
        if(score==null){
            //如果分数不存在
            boolean isSuccess=update().setSql("liked=liked+1").eq("id",id).update();
            //链式调用,第一个updata()是链式调用的起点，初始化并返回一个对象,最后一个updata()进行更新操作
        if(isSuccess){
            stringRedisTemplate.opsForZSet().add("blog:liked:"+id,userId.toString(),System.currentTimeMillis());
            //把分数保存到redis里
            // 在Redis中保存用户ID和点赞时间戳
        }
        }else{
            // 如果当前用户已经点赞该博客，则执行取消点赞操作
            boolean isSuccess=update().setSql("liked=liked-1").eq("id",id).update();
            // 更新数据库中该博客文章的点赞数（`liked` 字段减1）
            stringRedisTemplate.opsForZSet().remove("blog:liked:"+id,userId.toString());
            // 如果数据库更新成功，从Redis的ZSet中移除当前用户的点赞记录

        }
        return Result.ok();
        // 返回操作成功的结果
    }

    @Override
    public Result queryBlogLikes(Long id) {
        //查询某个博客的点赞用户
        String key="blog:liked:"+id;
//        页面id打包成key
        Set<String> top5=stringRedisTemplate.opsForZSet().range(key,0,4);
//        从 Redis 中获取点赞的用户 ID（前5名）
        if(top5==null||top5.isEmpty()){
            return Result.ok(Collections.emptyList());
        }
//        如果 Redis 中没有找到任何点赞用户（即 top5 为空或为 null），则直接返回一个空的结果
//        （Result.ok(Collections.emptyList())），表示没有人点赞。
        List<Long> ids=top5.stream().map(Long::valueOf).collect(Collectors.toList());
//        将获取的点赞用户 ID 转换为 Long 类型列表
        String idStr=StrUtil.join(",",ids);
//        .将用户 ID 列表转化为 SQL 查询时使用的字段顺序
       List<UserDTO> userDTOS=userService.query()
//        查询数据库中的用户信息
               .in("id",ids)
//               查找用户 ID 在 ids 列表中的记录。
               .last("ORDER BY FIELD(id,"+idStr+")").list()
               //执行查询，获取用户记录。
                .stream()
                .map(user -> BeanUtil.copyProperties(user, UserDTO.class))
//        将查询到的用户实体转换为 UserDTO 类型。
                .collect(Collectors.toList());
//       将结果收集为一个 List<UserDTO>。
        return null;
    }

    @Override
    public Result saveBlog(Blog blog) {
        //保存新博客
        UserDTO user = UserHolder.getUser();
        //获取当前用户信息
        blog.setUserId(user.getId());
        //
        boolean isUsccess=save(blog);
        if(!isUsccess){
            return Result.fail("新增笔记失败");
        }
        List<Follow> follows=followService.query().eq("follow_user_id",user.getId()).list();

        for(Follow follow:follows){
            Long userId = follow.getUserId();
            String key="feed:"+userId;
            stringRedisTemplate.opsForZSet().add(key,blog.getId().toString(),System.currentTimeMillis());
        }
        return Result.ok(blog.getId());
    }

    @Override
    public Result queryBlogOfFollow(Long max, Integer offset) {
        //查询当前用户关注的人的最新博客
        Long userId = UserHolder.getUser().getId();
        String key="blog:"+userId;
        Set<ZSetOperations.TypedTuple<String>> typedTuples=stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key,0,max,offset,2);
        if(typedTuples==null||typedTuples.isEmpty()){
            return Result.ok();
        }
        List<Long> ids=new ArrayList<>(typedTuples.size());
        long minTime=0;
        int os=1;
        for(ZSetOperations.TypedTuple<String> tuple:typedTuples){
            ids.add(Long.valueOf(tuple.getValue()));
            long time=tuple.getScore().longValue();
            if(time==minTime){
                os++;
            }else{
                minTime=time;
                os=1;
            }
        }
        String idStr=StrUtil.join(",",ids);
        List<Blog> blogs=query().in("id",ids).last("ORDER BY FIELD(id,"+idStr+")").list();
        for(Blog blog:blogs){
            queryBlogUser(blog);
            isBlogLiked(blog);
        }
        ScrollResult r=new ScrollResult();
        r.setList(blogs);
        r.setOffset(os);
        r.setMinTime(minTime);
        return Result.ok(r);
    }

    private void queryBlogUser(Blog blog) {
        //查询博客的用户信息
        Long userId = blog.getUserId();
        //获取发博客的用户的id
        User user = userService.getById(userId);
        //根据该博客用户的id,获取该用户信息
        //user:User(id=1010, phone=13263749891, password=,
        // nickName=user_kvrd8ossxl, icon=, createTime=2025-03-24T19:41:42,
        // updateTime=2025-03-24T19:41:42)
        blog.setName(user.getNickName());
        //该博客的用户名字
        blog.setIcon(user.getIcon());
        //该博客的头像,照片
        System.out.println("userId:"+userId);
        System.out.println("user:"+user );
        System.out.println("name:"+user.getNickName());
        System.out.println("icon:"+user.getIcon());
    }
}
